package com.colt.contentcenter.aop.auth;

import com.colt.contentcenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthLoginAspect {

    private final JwtOperator jwtOperator;
//    加了@CheckAuthorization
    @Around("@annotation(com.colt.contentcenter.aop.auth.CheckAuthorization)")
    public Object CheckAuthorization(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            //1.验证token是否合法
            this.checkToken();
            //2.验证用户角色是否匹配
            HttpServletRequest request = this.getHttpServletRequest();
            String role = (String) request.getAttribute("role");
            //用户获取到的role和注解上的对比
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //可拿到添加了@CheckAuthorization注解方法的定义
            Method method = signature.getMethod();
            //通过反射注解
            CheckAuthorization annotation = method.getAnnotation(CheckAuthorization.class);
            //获取注解中的值
            String value = annotation.value();
            if(!Objects.equals(role,value)){
                throw new SecurityException("用户角色无权访问该资源！");
            }
        } catch (Throwable throwable) {
            throw new SecurityException("用户角色无权访问该资源！",throwable);
        }
        return joinPoint.proceed();
    }

    //只要打了@CheckLogin的方法都会走到这里来
    @Around("@annotation(com.colt.contentcenter.aop.auth.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint joinPoint) throws Throwable {
        this.checkToken();
        return joinPoint.proceed();
    }

    private void checkToken() {
        try {
            //1.从header获取token
            HttpServletRequest request = getHttpServletRequest();
            String token = request.getHeader("X-Token");
            //2.校验token合法性或是否过期  不合法抛异常   合法放行
            Boolean isvalid = jwtOperator.validateToken(token);
            if (!isvalid){
                throw new SecurityException("token不合法或者已过期！");
            }
            //3.若校验成功，就将用户信息设置到request的attribute里面
            //用户信息
            Claims claims = jwtOperator.getClaimsFromToken(token);
            request.setAttribute("id",claims.get("id"));
            request.setAttribute("wxNickName",claims.get("wxNickName"));
            request.setAttribute("role",claims.get("role"));
        }catch (Throwable throwable){
            throw new SecurityException("token 不合法");
        }

    }

    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) attributes;
        return servletRequestAttributes.getRequest();
    }


}
